import 'package:detect/widgets/other/sliver_header_delegate.dart';
import 'package:detect/widgets/scroll_listener.dart';
import 'package:flutter/material.dart';

class CustomTable<T> extends StatefulWidget {
  final List<T> data;
  final List<Widget> fields;
  final List<Widget> Function(BuildContext context, int index, T data) itemBuilder;
  final void Function(int index, T data)? onTapItem;
  final Axis direction;
  final bool shrinkWrap;
  final BorderRadiusGeometry? borderRadius;
  final Color background;
  final Color? hoverColor;
  final Color? headColor;
  final double headSize;
  final TextStyle? headTextStyle;
  final EdgeInsets headPadding;
  final EdgeInsets headCellPadding;
  final BoxBorder? headBorder;
  final BoxBorder? headCellBorder;
  final Color? itemColor;
  final double itemSize;
  final TextStyle? itemTextStyle;
  final EdgeInsets itemPadding;
  final EdgeInsets itemCellPadding;
  final BoxBorder? itemBorder;
  final BoxBorder? itemCellBorder;

  const CustomTable({
    super.key,
    required this.data,
    required this.fields,
    required this.itemBuilder,
    this.onTapItem,
    this.direction = Axis.vertical,
    this.shrinkWrap = false,
    this.borderRadius,
    this.background = Colors.transparent,
    this.hoverColor,
    this.headColor,
    this.headSize = 40,
    this.headTextStyle,
    this.headPadding = EdgeInsets.zero,
    this.headCellPadding = EdgeInsets.zero,
    this.headBorder,
    this.headCellBorder,
    this.itemColor,
    this.itemSize = 40,
    this.itemTextStyle,
    this.itemPadding = EdgeInsets.zero,
    this.itemCellPadding = EdgeInsets.zero,
    this.itemBorder,
    this.itemCellBorder,
  });

  @override
  State<CustomTable<T>> createState() => _CustomTableState<T>();
}

class _CustomTableState<T> extends State<CustomTable<T>> {
  @override
  Widget build(BuildContext context) => Material(
        color: widget.background,
        clipBehavior: Clip.antiAlias,
        borderRadius: widget.borderRadius,
        child: ScrollListener(
          builder: (context, controller) => CustomScrollView(
            controller: controller,
            shrinkWrap: widget.shrinkWrap,
            scrollDirection: widget.direction,
            slivers: [
              SliverPersistentHeader(
                pinned: true,
                delegate: CustomSliverPersistentHeaderDelegate.fixedSize(
                  size: widget.headSize,
                  child: DefaultTextStyle(
                    maxLines: 1,
                    softWrap: false,
                    textAlign: TextAlign.center,
                    overflow: TextOverflow.ellipsis,
                    style: widget.headTextStyle ?? const TextStyle(),
                    child: Container(
                      width: widget.direction == Axis.vertical ? null : widget.headSize,
                      height: widget.direction == Axis.horizontal ? null : widget.headSize,
                      padding: widget.headPadding,
                      decoration: BoxDecoration(color: widget.headColor, border: widget.headBorder),
                      child: _head,
                    ),
                  ),
                ),
              ),
              SliverFixedExtentList(
                delegate: SliverChildBuilderDelegate(
                  (context, index) => DefaultTextStyle(
                    softWrap: true,
                    textAlign: TextAlign.center,
                    overflow: TextOverflow.ellipsis,
                    style: widget.itemTextStyle ?? const TextStyle(),
                    child: Ink(
                      padding: widget.itemPadding,
                      decoration: BoxDecoration(color: widget.itemColor, border: widget.itemBorder),
                      child: InkWell(
                        onTap: () => widget.onTapItem?.call(index, widget.data[index]),
                        hoverColor: widget.hoverColor,
                        focusColor: widget.hoverColor,
                        highlightColor: widget.hoverColor,
                        splashColor: widget.hoverColor,
                        child: _renderItem(index),
                      ),
                    ),
                  ),
                  childCount: widget.data.length,
                ),
                itemExtent: widget.itemSize,
              ),
            ],
          ),
        ),
      );

  Widget get _head {
    List<Widget> children = widget.fields
        .map<Widget>((child) => Expanded(
              child: Container(
                width: widget.direction == Axis.vertical ? null : widget.headSize,
                height: widget.direction == Axis.horizontal ? null : widget.headSize,
                padding: widget.headCellPadding,
                decoration: BoxDecoration(border: widget.headCellBorder),
                // child: FittedBox(fit: BoxFit.scaleDown, child: child),
                child: Center(child: child),
              ),
            ))
        .toList();
    return widget.direction == Axis.vertical
        ? Row(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: children,
          )
        : Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: children,
          );
  }

  Widget _renderItem(int index) {
    List<Widget> children = widget
        .itemBuilder(context, index, widget.data[index])
        .map<Widget>((child) => Expanded(
              child: Container(
                width: widget.direction == Axis.vertical ? null : widget.itemSize,
                height: widget.direction == Axis.horizontal ? null : widget.itemSize,
                alignment: Alignment.center,
                padding: widget.itemCellPadding,
                decoration: BoxDecoration(border: widget.itemCellBorder),
                // child: FittedBox(fit: BoxFit.scaleDown, child: child),
                child: Center(child: child),
              ),
            ))
        .toList();
    return widget.direction == Axis.vertical
        ? Row(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: children,
          )
        : Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: children,
          );
  }
}
